#include "Channel.hpp"

// 构造函数，初始化成员变量并设置文件描述符
Channel::Channel(int fd) :fd_(fd), events_(0), retEvents_(0), isValid_(true) {};

// 析构函数，关闭文件描述符
Channel::~Channel() {
    closeChannel();
}

// 关闭文件描述符
void Channel::closeChannel() {
    LOG << "Channel::closeChannel() fd: " << fd_;
    if (fd_ >= 0) {
        ::close(fd_);
        fd_ = -1;
        isValid_ = false;
    }
}

// IO事件的回调函数 EventLoop中调用Loop开始事件循环 会调用Poll得到就绪事件 
// 然后依次调用此函数处理就绪事件
void Channel::handleEvents() {
    // 触发挂起事件 并且没触发可读事件
    if ((retEvents_ & EPOLLHUP) && !(retEvents_ & EPOLLIN)) {
        //如果对端关闭写（HUP）但没有可读数据（IN），则直接返回。这通常是安全的，因为后续的 EPOLLRDHUP 检查（包含在 EPOLLIN | EPOLLPRI | EPOLLRDHUP 中）应该会触发 read_handler，并在 read 返回 0 时进行清理。
        return;
    }
    // 触发错误事件
    if (retEvents_ & EPOLLERR) {
        LOG << "Connection error on fd: " << fd_ << " errno: " << errno;
        if (errorCallback_) {
            errorCallback_();
        }
        return;
    }
    // 触发可读事件 | 高优先级可读 | 对端（客户端）关闭连接
    if (retEvents_ & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
        if (readCallback_) {
            readCallback_();
        }
    }
    // 触发可写事件
    if (retEvents_ & EPOLLOUT) {
        if (writeCallback_) {
            writeCallback_();
        }
    }
}


// 新增内存池实现
ChannelPool::ChannelPool() {
    std::lock_guard<std::mutex> lock(mutex_);
    for (size_t i = 0; i < INIT_POOL_SIZE; ++i) {
        pool_.push_back(ChannelPtr(
            new Channel(-1), 
            [this](Channel* p) { 
                release(ChannelPtr(p)); 
            }
        ));
    }
}

ChannelPool::~ChannelPool() {
    std::lock_guard<std::mutex> lock(mutex_);
    pool_.clear();
}

ChannelPtr ChannelPool::acquire(int fd) {
    LOG<<"ChannelPool::acquire() fd: "<<fd;
    LOG << "ChannelPool::acquire() fd: " << fd << " [Pool size: " << pool_.size() << "]"; 
    std::lock_guard<std::mutex> lock(mutex_);
    if (pool_.empty()) {
        // 池空时扩展容量
        return ChannelPtr(
            new Channel(fd),
            [this](Channel* p) { 
                release(ChannelPtr(p)); 
            }
        );
    }
    
    auto channel = pool_.back();
    pool_.pop_back();
    // channel->setFd(fd);
    // channel->setValid(true);
    // channel->setEvents(0);
    // channel->setRetEvents(0);
    // channel->set_read_handler(nullptr);
    // channel->set_write_handler(nullptr);
    channel->fd_ = fd;
    channel->events_ = 0;
    channel->isValid_ = true;
    channel->retEvents_ = 0;
    channel->readCallback_ = nullptr;
    channel->writeCallback_ = nullptr;
    return channel;
}

void ChannelPool::release(ChannelPtr channel) {
    LOG<<"ChannelPool::release() fd: "<<channel->getFd();
    LOG << "ChannelPool::release() fd: " << channel->getFd() << " [Pool size: " << pool_.size() << "]";
    std::lock_guard<std::mutex> lock(mutex_);
    channel->closeChannel();
    pool_.push_back(channel);
}



